/* Copyright (c) 2004-2023 HuangCong.info. All rights reserved. */
package com.core.enums;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.annotation.JSONCreator;
import com.alibaba.fastjson2.annotation.JSONType;
import com.baomidou.mybatisplus.annotation.EnumValue;
import lombok.AllArgsConstructor;
import lombok.Getter;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * ResultCodeEnums
 *
 * @author Dick
 * @version 1.0.0
 * @since 2025/7/29
 */
@Getter
@AllArgsConstructor
@JSONType(writeEnumAsJavaBean = true)
public enum ResultCodeEnums  {
    // 成功类
    SUCCESS("200", "操作成功"),

    // 客户端请求错误
    BAD_REQUEST("400", "请求参数错误"),
    UNAUTHORIZED("401", "未认证"),
    FORBIDDEN("403", "无权限访问"),
    NOT_FOUND("404", "请求资源不存在"),
    METHOD_NOT_ALLOWED("405", "请求方式不支持"),

    // 服务端错误
    INTERNAL_SERVER_ERROR("500", "服务器内部错误"),
    SERVICE_UNAVAILABLE("503", "服务不可用"),
    GATEWAY_TIMEOUT("504", "网关超时"),

    // 参数错误
    PARAM_MISSING("1000", "缺少必要参数"),
    PARAM_INVALID("1001", "参数无效"),
    PARAM_TYPE_MISMATCH("1002", "参数类型不匹配"),

    // 业务类错误
    DATA_NOT_EXIST("2001", "数据不存在"),
    DATA_EXISTED("2002", "数据已存在"),
    OPERATION_FAILED("2003", "操作失败"),
    OPERATION_DENIED("2004", "操作被拒绝"),

    // 用户模块
    USER_NOT_LOGIN("3001", "用户未登录"),
    USER_NOT_FOUND("3002", "用户不存在"),
    USER_PASSWORD_ERROR("3003", "密码错误"),

    // 权限模块
    ROLE_NOT_FOUND("3101", "角色不存在"),
    PERMISSION_DENIED("3102", "权限不足"),
    UNKNOWN("--", "未知枚举参数"),
    ;

    @EnumValue
    private final String code;
    private final String message;

    private static final Map<String, ResultCodeEnums> CODE_MAP;
    private static final Map<String, ResultCodeEnums> NAME_MAP;

    static {
        CODE_MAP = Collections.unmodifiableMap(
                Stream.of(values())
                        .collect(Collectors.toMap(ResultCodeEnums::getCode, e -> e, (e1, e2) -> e1))
        );
        NAME_MAP = Collections.unmodifiableMap(
                Stream.of(values())
                        .collect(Collectors.toMap(e -> e.name().toLowerCase(), e -> e, (e1, e2) -> e1))
        );
    }

    /**
     * 通过code查找枚举，null安全，找不到返回UNKNOWN
     */
    public static ResultCodeEnums getByCode(String code) {
        if (StrUtil.isBlank(code)) {
            return UNKNOWN;
        }
        return CODE_MAP.getOrDefault(code, UNKNOWN);
    }

    /**
     * 通过name查找枚举，忽略大小写，找不到返回UNKNOWN
     */
    public static ResultCodeEnums getByName(String name) {
        if (StrUtil.isBlank(name)) {
            return UNKNOWN;
        }
        return NAME_MAP.getOrDefault(name.toLowerCase(), UNKNOWN);
    }

    /**
     * 获取所有枚举列表，返回不可修改集合
     */
    public static List<ResultCodeEnums> getAllEnum() {
        return List.of(values());
    }

    /**
     * 获取所有code列表
     */
    public static List<String> getAllEnumCode() {
        return getAllEnum().stream()
                .map(ResultCodeEnums::getCode)
                .toList();
    }

    /**
     * 判断当前枚举是否包含于传入枚举列表中
     */
    public boolean isInList(ResultCodeEnums... values) {
        if (values == null) {
            return false;
        }
        for (ResultCodeEnums v : values) {
            if (this == v) {
                return true;
            }
        }
        return false;
    }

    /**
     * 通过code获取对应的message
     */
    public static String getMsgByCode(String code) {
        return getByCode(code).getMessage();
    }


    /**
     * 通用安全获取字段方法，避免NPE
     */
    public static <T> T safeGet(ResultCodeEnums enumValue, Function<ResultCodeEnums, T> mapper, T defaultValue) {
        return enumValue == null ? defaultValue : mapper.apply(enumValue);
    }

    public static <T> T safeGet(ResultCodeEnums enumValue, Function<ResultCodeEnums, T> mapper) {
        return safeGet(enumValue, mapper, null);
    }

    /**
     * 返回code-message映射（不可变）
     */
    public static Map<String, String> maps() {
        return Collections.unmodifiableMap(
                Arrays.stream(values())
                        .collect(Collectors.toMap(ResultCodeEnums::getCode, ResultCodeEnums::getMessage, (m1, m2) -> m1))
        );
    }

    /**
     * 反序列化JSON时使用，null或无匹配时返回UNKNOWN
     */
    @JSONCreator
    public static ResultCodeEnums deserialize(String code) {
        return getByCode(code);
    }

    /**
     * 获取随机枚举（不含UNKNOWN）
     */
    public static ResultCodeEnums getRandomEnum() {
        return getRandomEnum(Collections.emptyList());
    }

    /**
     * 获取随机枚举，忽略指定枚举
     */
    public static ResultCodeEnums getRandomEnum(ResultCodeEnums... ignores) {
        return getRandomEnum(Arrays.asList(ignores));
    }

    /**
     * 获取随机枚举，忽略指定枚举列表
     */
    public static ResultCodeEnums getRandomEnum(Collection<ResultCodeEnums> ignores) {
        List<ResultCodeEnums> candidates = getAllEnum().stream()
                .filter(v -> v != UNKNOWN && !ignores.contains(v))
                .collect(Collectors.toList());
        return candidates.isEmpty() ? UNKNOWN : RandomUtil.randomEle(candidates);
    }

    /**
     * 获取多个随机枚举，数量受限于枚举数量和忽略列表
     */
    public static List<ResultCodeEnums> getRandomEnums(int count) {
        return getRandomEnums(Collections.emptyList(), count);
    }

    /**
     * 获取多个随机枚举，忽略指定列表
     */
    public static List<ResultCodeEnums> getRandomEnums(Collection<ResultCodeEnums> ignores, int count) {
        List<ResultCodeEnums> candidates = getAllEnum().stream()
                .filter(v -> v != UNKNOWN && !ignores.contains(v))
                .collect(Collectors.toList());
        return RandomUtil.randomEleList(candidates, count);
    }
}
